﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SongClassifier
{
    public partial class WaveForm : Form
    {
        int[] value = null;
        int maxV = 0;
        short[] data = null;

        public WaveForm()
        {
            InitializeComponent();
            this.panel1.Paint += panel_Paint;
            this.panel1.Resize += panel_Resize;
        }

        private void panel_Paint(object sender, PaintEventArgs e)
        {
            Draw();
        }

        public void panel_Resize(object sender, EventArgs e)
        {
            AjustSize();
            Draw();
        }

        public void AjustSize()
        {
            if (textBoxWavPath.Text == "")
                return;
            maxV = 0;
            value = new int[panel1.Width + 1];
            WaveAccess wav = new WaveAccess(textBoxWavPath.Text);

            int xLen = this.panel1.Width;
            int ylen = this.panel1.Height;
            int dataLen = wav.Data.Length;
            data = wav.Data;
            int unitSize = (int)Math.Ceiling((dataLen + 0f) / xLen);
            if (unitSize == 0)
                unitSize = 1;
            this.labelUnitSize.Text = unitSize.ToString();

            int avg = 0;
            int count = 0;
            for (int i = 0; i < dataLen; i++)
            {
                avg += wav.Data[i];
                if (i % unitSize == unitSize - 1 || i == dataLen - 1)
                {
                    avg /= unitSize;
                    value[count] = avg;
                    if (maxV < Math.Abs(avg))
                        maxV = Math.Abs(avg);
                    count++;
                    avg = 0;
                }
            }
        }

        public void Draw()
        {
            Graphics g = this.panel1.CreateGraphics();
            int x0 = 0;
            int y0 = panel1.Height / 2;

            GraphDraw.Draw(g, value, x0, y0, maxV);
        }

        private void buttonFFT_Click(object sender, EventArgs e)
        {
            int pieceLen = 1024;
            double[] data_r = new double[pieceLen];
            double[] data_i = new double[pieceLen];
            double[] result_r = new double[pieceLen];
            double[] result_i = new double[pieceLen];

            FftForm fft = new FftForm();
            fft.Show();
            for (int i = 0; i < data.Length; i++)
            {
                data_r[i%pieceLen] = (int)data[i];
                data_i[i%pieceLen] = 0;

                if (i % pieceLen == pieceLen - 1)
                {
                    FFT.Dit2_FFT(ref data_r, ref data_i, ref result_r, ref result_i);
                    fft.SnapShot(result_r, result_i);
                    //System.Threading.Thread.Sleep(1);
                }
            }
            //new FftForm(result_r, result_i).Show();
        }

        private void buttonDraw_Click(object sender, EventArgs e)
        {
            AjustSize();
            Draw();
        }

        private void buttonSearchPath_Click(object sender, EventArgs e)
        {
            OpenFileDialog dia = new OpenFileDialog();
            if (dia.ShowDialog() == DialogResult.OK)
            {
                textBoxWavPath.Text = dia.FileName;
            }
        }

        private void buttonFreq_Click(object sender, EventArgs e)
        {
            int freq = int.Parse(textBoxFreq.Text);
            FftForm fft = new FftForm();
            DrawCertainFreq(freq, fft, true);
            //FreqDeviList freqDeviList = new FreqDeviList();
            //for (freq = 0; freq < 1024; freq+=10)
            //{
            //    double devi = DrawCertainFreq(freq, fft,false);
            //    freqDeviList.Add(devi, freq);
            //    Console.WriteLine("freq = " + freq + " , devi = " + devi);
            //}
            //Console.WriteLine(freqDeviList.GetFirst().ToString());
            //Console.WriteLine(freqDeviList.GetLast().ToString());
        }

        /// <summary>
        /// return the wavLen devi of a certain freq
        /// </summary>
        /// <param name="freq"></param>
        /// <param name="fft"></param>
        /// <returns></returns>
        public double DrawCertainFreq(int freq, FftForm fft,bool show)
        {
            int pieceLen = 1024;
            double[] data_r = new double[pieceLen];
            double[] data_i = new double[pieceLen];
            double[] result_r = new double[pieceLen];
            double[] result_i = new double[pieceLen];

            double[] intensity_r = new double[data.Length / pieceLen + 1];
            double[] intensity_i = new double[data.Length / pieceLen + 1];
            int count = 0;

            for (int i = 0; i < data.Length; i++)
            {
                data_r[i % pieceLen] = (int)data[i];
                data_i[i % pieceLen] = 0;

                if (i % pieceLen == pieceLen - 1)
                {
                    FFT.Dit2_FFT(ref data_r, ref data_i, ref result_r, ref result_i);
                    intensity_r[count] = result_r[freq];
                    intensity_i[count] = result_i[freq];
                    count++;
                }
            }
            if (show)
            {
                fft.Show();
                fft.SnapShot(intensity_r, intensity_i);
            }
            double devi = FreqDeviList.CalculateDevi(intensity_r, intensity_i);
            return devi;
        }
    }
}
